﻿// ----------------------------------------------------------------------------
//  Copyright (C) 成都联宇创新科技有限公司 版权所有。 
//      
//  文件名：CryptoBase.cs
//  文件功能描述：
//  创建标识：骆智慧 2016/03/02 23:28
//     
//  修改标识：骆智慧  2016/03/10/06:40
//  修改描述：
//  ----------------------------------------------------------------------------

#region 导入名称空间

using System;
using System.Text;

#endregion

namespace LightWork.Cryptography
{
    public abstract class CryptoBase : ICryptoService
    {
        /// <summary>
        /// 加密数据
        /// </summary>
        /// <param name="plaintext">明文</param>
        /// <param name="password">用于派生密钥的密码</param>
        /// <param name="salt">用于派生密钥的密钥salt</param>
        /// <param name="iterations">操作的迭代数</param>
        /// <remarks>salt 大小必须等于或大于 8 字节，并且迭代次数必须大于零。 建议的最小迭代次数为 1000</remarks>
        /// <returns></returns>
        public abstract byte[] Encrypt(byte[] plaintext, byte[] password, byte[] salt, int iterations);

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="plaintext">明文</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public abstract string Encrypt(byte[] plaintext, byte[] password);

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="plaintext">明文</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public string Encrypt(string plaintext, string password)
        {
            return Encrypt(ToBytes(plaintext), ToBytes(password));
        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="plaintext">明文</param>
        /// <returns></returns>
        public string Encrypt(string plaintext)
        {
            return Encrypt(ToBytes(plaintext), DefaultPassword);
        }

        /// <summary>
        /// 解密数据
        /// </summary>
        /// <param name="ciphertext">密文</param>
        /// <param name="password">用于派生密钥的密码</param>
        /// <param name="salt">用于派生密钥的密钥salt</param>
        /// <param name="iterations">操作的迭代数</param>
        /// <remarks>salt 大小必须等于或大于 8 字节，并且迭代次数必须大于零。 建议的最小迭代次数为 1000</remarks>
        /// <returns></returns>
        public abstract byte[] Decrypt(byte[] ciphertext, byte[] password, byte[] salt, int iterations);

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="ciphertext">密文</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public abstract string Decrypt(byte[] ciphertext, byte[] password);

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="ciphertext">密文</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public string Decrypt(string ciphertext, string password)
        {
            return Decrypt(FromHex(ciphertext), ToBytes(password));
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="ciphertext">密文</param>
        /// <returns></returns>
        public string Decrypt(string ciphertext)
        {
            return Decrypt(FromHex(ciphertext), DefaultPassword);
        }

        /// <summary>
        /// 默认字符串编码
        /// </summary>
        public Encoding DefaultEncoding { get; set; }

        /// <summary>
        /// 默认密码
        /// </summary>
        public byte[] DefaultPassword { get; set; }

        /// <summary>
        /// 默认盐值
        /// </summary>
        public byte[] DefaultSalt { get; set; }

        /// <summary>
        /// 转换字符串为Byte数组
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private byte[] ToBytes(string input)
        {
            return DefaultEncoding.GetBytes(input);
        }

        /// <summary>
        /// 转Byte数组为换字符串
        /// </summary>
        /// <param name="byteArray"></param>
        /// <returns></returns>
        public string FromBytes(byte[] byteArray)
        {
            return DefaultEncoding.GetString(byteArray);
        }

        /// <summary>
        /// 16进制字符串还原
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        public byte[] FromHex(string hexString)
        {
            hexString = hexString.Replace("-", "");
            var raw = new byte[hexString.Length / 2];
            for (var i = 0; i < raw.Length; i++)
                raw[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);

            return raw;
        }
    }
}